#include <stdio.h>  // for printf
#include <string.h> // for memory operation
#include <stdlib.h>
#include <unistd.h>  // for sleep
#include "ohos_init.h"
#include "cmsis_os2.h"

#include "wifi_device.h"
#include "wifi_hotspot.h"
#include "wifi_error_code.h"
#include "lwip/netifapi.h"
#include "lwip/api_shell.h"
#include "lwip/ip4_addr.h"
#include "lwip/netif.h"
#include "lwip/netifapi.h"
#include "iot_uart.h"
#include "WifiSta.h"

#include "MQTTClient.h"
#include "cJSON.h"
#define SSID "Nice"
#define KEY "12312312"
#define ZB_UART_BAUDRATE 9600
#define ZB_UART_IDX_1 1
#define TCP_PORT 5552
#define TCP_BACKLOG 8
#define TCP_NUM 3//最多3个超了无法accept a envi b flame c holeman
#define OPEN "287"
#define MOTOR_DIR1 "297"
#define MOTOR_DIR2 "2A7"

#define HOST_ADDR "baaeb697c9.st1.iotda-device.cn-north-4.myhuaweicloud.com"
#define SERVICE_ID "Agriculture"
#define DEVICE_ID "668c8ea85830dc113ecb9728_Fan_iot_0_0_2024070901"
#define DEVICE_USER "668c8ea85830dc113ecb9728_Fan_iot"
#define DEVICE_PWD "4915f2fa5cf9ed544fe309a32e12e73fecd05c1a429ff6208f76368041cfb849"
#define TOPIC_PUBLISH "$oc/devices/"DEVICE_ID"/sys/properties/report"
#define TPOIC_SUBCRIB "$oc/devices/"DEVICE_USER"/sys/commands/#"
#define TOPIC_RESPONSE "$oc/devices/"DEVICE_USER"/sys/commands/response/"

#define ledOn "ON"
static char recvbuf [512] ={0};
static char uart_buff [512] = {0};
static unsigned char send_mqttBuf[1000];
static unsigned char recv_mqttBuf[1000];

char temp_str[20] = {0},humi_str[20] = {0},light_str [20] = {0},flame_str[20] = {0},manhole_str[10] = {0},music_str[10] = {0};
float temp,humi,light,flame;
MQTTClient client;
Network network;

int sock_fd = 0,flag = 0,music,id_flag,ERROR;
typedef struct tcp_ip{
    int new_fd;
    struct in_addr sin_addr;
    int flag;//标记是否设置ip地址
}tcp_ip;
tcp_ip fd[8];
int GatewayUartTask();
void TCPServerTask(void);
void MqttTask(void);
void Find(int type,char *str);
int GatewayUartInit(void);
void messageHandle(MessageData *data);
void message_Cmdback(char *data);
static void TCPServerDemo(void)
{
    osThreadAttr_t attr;

    attr.name = "GatewayUartTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 1024 * 10;
    attr.priority = osPriorityNormal;
    attr.name = "GatewayUartTask";
    osThreadNew((osThreadFunc_t)GatewayUartTask, NULL, &attr);
    printf("success to create GatewayUartTask!\r\n");
    attr.name = "MqttTask";
    osThreadNew(MqttTask,NULL,&attr);
    attr.name = "TCPTask";
    osThreadNew((osThreadFunc_t)TCPServerTask, NULL, &attr);
    printf("success to create TCPServerTask!\r\n");
}

int GatewayUartTask()
{
    int ret = 0;
    /* UART初始化 */
    GatewayUartInit();
    osDelay(400);
    
    /* 等待TCP客户端连接，才转发数据 */
    while(fd[TCP_NUM - 1].new_fd == 0) {
        osDelay(100);
    }
    int gateCount;
    while(1)
    {
        memset_s(uart_buff, sizeof(uart_buff), 0, sizeof(uart_buff));
        //通过串口1接收数据
        ret = IoTUartRead(ZB_UART_IDX_1, uart_buff, sizeof(uart_buff));

        if (ret > 0 && fd[TCP_NUM - 1].new_fd != 0) {
            if(id_flag == 1 ){
                if((strstr(uart_buff, "1E6324") != NULL)){//对
                    gateCount ++;
                    id_flag = 0;
                    if(gateCount > 3){//延时防止频繁触发
                        memset_s(music_str, sizeof(music_str), 0, sizeof(music_str));
                        //开门
                        IoTUartWrite(ZB_UART_IDX_1, OPEN, strlen(OPEN));
                        music = 1;
                        gateCount = 0;
                        sprintf(music_str,"%d",music);
                    }
                }else {
                    gateCount ++;
                    id_flag = 0;
                    if(gateCount > 3){
                        memset_s(music_str, sizeof(music_str), 0, sizeof(music_str));
                        music = 2;
                        gateCount = 0;
                        sprintf(music_str,"%d",music);
                    }
                }
            }
            if(strstr(uart_buff, "ID") != NULL){
                id_flag = 1;
            }
            printf("Uart1 read data:%s \r\n", uart_buff);
            // 将串口数据转发到各个TCP客户端
            if ((ret = send(fd[TCP_NUM - 1].new_fd, uart_buff, ret, 0)) == -1)
            {
                printf("GatewayUartTask:send failed! \r\n");
            } else {
                printf("GatewayUartTask:transfer to TCP client \r\n");
            }
        }
        usleep(100);
    }

    return 0;
}
void TCPServerTask(void)
{
    //服务端地址信息
    struct sockaddr_in server_sock;

    //客户端地址信息
    struct sockaddr_in client_sock;
    int sin_size;

    //连接Wifi
    WifiConnect(SSID, KEY);
    
    //创建socket
    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        printf("socket is error\r\n");
        exit(1);
    }

    // 绑定IP地址等参数
    bzero(&server_sock, sizeof(server_sock));
    server_sock.sin_family = AF_INET;
    server_sock.sin_addr.s_addr = htonl(INADDR_ANY);
    server_sock.sin_port = htons(TCP_PORT);

    //调用bind函数绑定socket和地址
    if (bind(sock_fd, (struct sockaddr *)&server_sock, sizeof(struct sockaddr)) == -1)
    {
        printf("bind is error\r\n");
        exit(1);
    }

    //调用listen函数监听(指定port监听)
    if (listen(sock_fd, TCP_BACKLOG) == -1)
    {
        printf("listen is error\r\n");
        exit(1);
    }

    printf("start accept\r\n");
    int i = 0;
    //调用accept函数接受客户端连接请求
    while(1)
    {
        if(i > TCP_NUM - 1) i = 0;
        sin_size = sizeof(struct sockaddr_in);

        if ((fd[i].new_fd = accept(sock_fd, (struct sockaddr *)&client_sock, (socklen_t *)&sin_size)) == -1)
        {
            printf("accept");
            continue;
        }

        printf("accept addr\r\n");
        fd[i].sin_addr = client_sock.sin_addr;//获取客户端ip

        // printf("%d\n",client_sock.sin_addr);
        // printf("accept client addr:%s",inet_ntoa(client_sock.sin_addr));
        i++;
        printf("%d\n",i);
        //处理目标
        int j = 0;
        uint32_t a,b,c;
        ssize_t ret;
        while (i > TCP_NUM - 1)//数量判断成功后开始接收
        {
            if(j > i - 1) {
                j = 0;
            }
            memset_s(recvbuf, sizeof(recvbuf), 0, sizeof(recvbuf));
            if ((ret = recv(fd[j].new_fd, recvbuf, sizeof(recvbuf), 0)) == -1)
            {
                printf("recv error \r\n");
            }
            else
            {	
                printf("recv :%s\r\n", recvbuf);
                //通过串口1发送数据
                //IoTUartWrite(ZB_UART_IDX_1, (unsigned char *)recvbuf, strlen(recvbuf));
            }
            if(strstr(recvbuf, "A") != NULL){
                if(fd[j].flag == 0){//10位 可能有一位负号
                    char *ip [12] = {0};//10位 +可能有一位负号
                    strncpy(ip,recvbuf + 1,11);
                    sscanf(ip, "%d", &a);
                    if(a == (uint32_t)fd[j].sin_addr.s_addr) {
                        fd[j].flag = 1;
                        //printf("ok1\n");
                    }
                }else if(fd[j].flag == 1){
                    strncpy(temp_str,recvbuf + 1,9);
                    strncpy(humi_str,recvbuf + 11,9);
                    strncpy(light_str,recvbuf + 21,9);
                    sscanf(temp_str, "%f", &temp);
                    sscanf(humi_str, "%f", &humi);
                    sscanf(light_str,"%f",&light);
                }else ERROR = 1;//printf("ERRPR!!!\n");
            }else printf("NULL\n");

            if(strstr(recvbuf,"B") != NULL){
                if(fd[j].flag == 0){//10位 可能有一位负号
                    char *ip[12] = {0};//10位 +可能有一位负号
                    strncpy(ip,recvbuf + 1,11);
                    sscanf(ip, "%d", &c);
                    if(c == (uint32_t)fd[j].sin_addr.s_addr) {
                        fd[j].flag = 2;
                    }
                }else if(fd[j].flag == 2){
                    strncpy(flame_str,recvbuf + 1,9);
                    sscanf(flame_str, "%f", &flame);
                }else ERROR = 1;//printf("ERROR!!!\n");
            }else printf("NULL\n");

            if(strstr(recvbuf,"C") != NULL){
                if(fd[j].flag == 0){//10位 可能有一位负号
                    char *ip[12] = {0};//10位 +可能有一位负号
                    strncpy(ip,recvbuf + 1,11);
                    sscanf(ip, "%d", &c);
                    if(c == (uint32_t)fd[j].sin_addr.s_addr) {
                        fd[j].flag = 3;
                    }
                }else if(fd[j].flag == 3){
                    strncpy(manhole_str,recvbuf + 1,3);
                    if(strcmp(manhole_str,"ON") == 0) IoTUartWrite(ZB_UART_IDX_1, MOTOR_DIR1, strlen(MOTOR_DIR1));
                    flag = 1;
                }else ERROR = 1;//printf("ERROR!!!\n");
            }else printf("NULL\n");

            j++;
            usleep(1000);
        }

        //close(new_fd);
        usleep(100);
    }
}
void MqttTask(void){
    sleep(4);
    NetworkInit(&network);
    printf("NetworkInit\n");
begin:    
    NetworkConnect(&network,HOST_ADDR,1883);
    printf("MqttClinetInit\n");
    MQTTClientInit(&client,&network,2000,send_mqttBuf,sizeof(send_mqttBuf),recv_mqttBuf,sizeof(recv_mqttBuf));
    //配置平台端MQTT连接
    MQTTString clientId = MQTTString_initializer;
    clientId.cstring = DEVICE_ID;
    MQTTString clientUser = MQTTString_initializer;
    clientUser.cstring = DEVICE_USER;
    MQTTString clientPwd = MQTTString_initializer;
    clientPwd.cstring = DEVICE_PWD;
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.clientID = clientId;
    data.username = clientUser;
    data.password = clientPwd;
    data.willFlag = 0;
    data.MQTTVersion = 4;
    data.keepAliveInterval = 60;
    data.cleansession = 1;
    printf("MQTTConect\n");
    int rc = MQTTConnect(&client,&data);
    if(rc != 0){
        printf("MQTTConect %d\n",rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        sleep(2);
        goto begin;
    }
    //配置订阅指令
    printf("MQTTSUBCRIBE\n");
    rc = MQTTSubscribe(&client,TPOIC_SUBCRIB,0,messageHandle);
    if(rc != 0){
        printf("MQTTSubscribe %d\n",rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        sleep(2);
        goto begin;
    }

    while(1){
        if(flag == 1){
            printf("===mqtt send\n");
            MQTTMessage message;
            char payload[100] = {0};
            cJSON *root = cJSON_CreateObject();
            if(root != NULL){
                cJSON *serv_arr = cJSON_AddArrayToObject(root,"services");
                cJSON *arr_item = cJSON_CreateObject();
                cJSON_AddStringToObject(arr_item,"service_id",SERVICE_ID);
                cJSON *pro_obj = cJSON_CreateObject();
                cJSON_AddItemToObject(arr_item,"properties",pro_obj);

                //JSON拼接
                cJSON_AddNumberToObject(pro_obj,"Temp",temp);
                cJSON_AddNumberToObject(pro_obj,"Humi",humi);
                cJSON_AddNumberToObject(pro_obj,"Light",light);
                cJSON_AddNumberToObject(pro_obj,"Mq7",flame);
                cJSON_AddStringToObject(pro_obj,"Manhole",manhole_str);
                cJSON_AddStringToObject(pro_obj,"Music",music_str);
                if(ERROR == 1) cJSON_AddStringToObject(pro_obj,"ERROR","ON");
                music = 0;//复位
                sprintf(music_str,"%d",music);
                cJSON_AddItemToArray(serv_arr,arr_item);
                char *play_str = cJSON_PrintUnformatted(root);
                strcpy(payload,play_str);
                cJSON_free(play_str);
                cJSON_Delete(root);
            }
            message.qos = 0;
            message.retained = 0;
            message.payload = payload;
            message.payloadlen = strlen(payload);
            if((rc = MQTTPublish(&client,TOPIC_PUBLISH,&message)) != 0){
                printf("MQTT Publish Failed\n");
                NetworkDisconnect(&network);
                MQTTDisconnect(&client);
                sleep(2);
                goto begin;
            }else {
                printf("mqtt publish success:%s\n",payload);
            }
            flag = 0;
        }
        MQTTYield(&client,2000);
    }
}
int GatewayUartInit(void)
{

    uint32_t ret;
    IotUartAttribute uart_attr = {

        //baud_rate: 9600
        .baudRate = ZB_UART_BAUDRATE,

        //data_bits: 8bits
        .dataBits = 8,
        .stopBits = 1,
        .parity = 0,
    };

    //Initialize uart driver
    ret = IoTUartInit(ZB_UART_IDX_1, &uart_attr);
    if (ret != 0)
    {
        printf("Failed to init uart! Err code = %d\r\n", ret);
        return;
    }
    printf("UART Test Start\r\n");
}
void Find(int type,char *str){//注意形参格式 直接穿"on"不得
int ret;
    for(int i = 0;i < TCP_NUM;i++){
        if(fd[i].flag == type){
            printf("str == %s\n",str);
        if ((ret = send(fd[i].new_fd, str, strlen(str)+1, 0)) == -1)
            {
                printf("send failed! \r\n");
            } else {
                printf("transfer to TCP client \r\n");
            }
        }
    }
}
char fan_str[20] = {0};
void messageHandle(MessageData *data){
    printf("messeage on topic:%s,data%s\n",data->topicName->lenstring.data,data->message->payload);
    char *request_id_idx = NULL;
    request_id_idx = strstr(data->topicName->lenstring.data,"request_id=");
    char request_id[50] = {0};
    strncpy(request_id,request_id_idx + 11,36);
    printf("requestId = %s\n",request_id);
    cJSON *root = cJSON_ParseWithLength(data->message->payload,data->message->payloadlen);
    if(root != NULL){
        cJSON *cmd_name = cJSON_GetObjectItem(root,"command_name");
        if(cmd_name != NULL){
            char *cmd_name_str = cJSON_GetStringValue(cmd_name);
            printf("command_name :%s\n",cmd_name_str);
            if(strcmp(cmd_name_str,"Control") ==0){
                cJSON *para_obj = cJSON_GetObjectItem(root,"paras");
                cJSON *status_obj = cJSON_GetObjectItem(para_obj,"Light");
                char *light_str = cJSON_GetStringValue(status_obj);
                if(light_str !=NULL) Find(1,light_str);

                status_obj = cJSON_GetObjectItem(para_obj,"Fan");
                float fan = cJSON_GetNumberValue(status_obj);
                if(fan != 0){
                    sprintf(fan_str,"%d",(unsigned short)fan);
                    strcat(fan_str,"Fan");
                    Find(1,fan_str);
                }

                //printf("led: %s,fan :%f\n",light_str,fan);
                cJSON_free(light_str);
            }
            if(strcmp(cmd_name_str,"Motor") ==0){
                cJSON *para_obj = cJSON_GetObjectItem(root,"paras");
                cJSON *status_obj = cJSON_GetObjectItem(para_obj,"Motor");
                char *motor_str = cJSON_GetStringValue(status_obj);
                if(motor_str !=NULL){
                    if(strcmp(motor_str,"le") == 0) IoTUartWrite(ZB_UART_IDX_1, MOTOR_DIR2, strlen(MOTOR_DIR2));
                    else if (strcmp(motor_str,"ri") == 0) IoTUartWrite(ZB_UART_IDX_1, MOTOR_DIR1, strlen(MOTOR_DIR1));
                }
                cJSON_free(motor_str);
            }
        }
        message_Cmdback(request_id);
        cJSON_Delete(root);
    }
}

//指令返回
void message_Cmdback(char *data){
    char retopic_str[128] = {0};
    sprintf(retopic_str,"%srequest_id=%s",TOPIC_RESPONSE,data);
    printf("retopic = %s\n",retopic_str);
    MQTTMessage message;
    char payload[200] = {0};
    message.qos = 0;
    message.retained = 0;
    sprintf(payload,"{\
    \"result_code\": 0,\
    \"response_name\": \"COMMAND_RESPONSE\",\
    \"paras\": {\
        \"result\": \"success\"\
    }\
    }");
    message.payload = payload;
    message.payloadlen = strlen(payload);
    int rc;
    if((rc = MQTTPublish(&client,retopic_str,&message)) != 0){
        printf("MessageCmdback Publish Failed\n");
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        sleep(2);
    }else {
        printf("MessageCmdback publish success:%s\n",payload);
    }
}
APP_FEATURE_INIT(TCPServerDemo);